package dao.hibernate;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.DOMWriter;
import org.hibernate.MappingException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import entities.Delegation;
import entities.LinkAssociation;
import entities.OwnerAssociation;
import entities.Status;
import entities.TreeAssociation;
import service.configuration.IConfiguration;
import service.configuration.NamingUtil;


@Service
public class HibernateUtilAsof extends HibernateUtil {
	
	@Autowired
	public HibernateUtilAsof(IConfiguration config) {
		super(config, "hibernate_asof.cfg.xml");
			
		try {
			// on ajoute les mappings : 
			addAsofMappings();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		try {
			// on initialise la SessionFactory :
			sessionFactory = hibernateConfig.buildSessionFactory();
		} catch (Throwable ex) {
			System.err.println("Initial SessionFactory creation failed." + ex);
			throw new ExceptionInInitializerError(ex);
		}
	}

	
	private void addAsofStatus(Document document) {
		addEnumProperty(document, NamingUtil.STATUS,
				"ASOF_STATUS", "true", Status.class.getName());
	}
	
	
	private void addAsofPassword(Document document) {
		addProperty(document, NamingUtil.PASSWORD,
				"string", "ASOF_PASSWORD");
	}
	
	
	private Document createAsofClassMapping(String className, String tableName) {
		Document document = DocumentHelper.createDocument();
		
		Element root = document.addElement("hibernate-mapping");
		Element entity = root.addElement("class")
						 .addAttribute("name", className)
						 .addAttribute("table", tableName);

		Element id = entity.addElement("id")
		.addAttribute("name", "id")
		.addAttribute("type", "long")
		.addAttribute("column", "ID");
		
		id.addElement("generator").addAttribute("class", "increment");
		
		return document;
	}

	
	private void addAsofTreeAssociationMapping(DOMWriter writer)
					throws MappingException, DocumentException {
		
		Document document = createAsofClassMapping(TreeAssociation.class.getName(), "ASOF_TREE");
		Element entity = document.getRootElement().element("class");
		
		addProperty(entity, "parentCode", "string", "PARENT");
		addProperty(entity, "childCode", "string", "CHILD");
		addProperty(entity, "parentType", "string", "PARENT_TYPE");
		addProperty(entity, "childType", "string", "CHILD_TYPE");
		addProperty(entity, "childOrder", "integer", "CHILD_ORDER");
		
		hibernateConfig.addDocument(writer.write(document));
		
		//System.out.println(document.asXML());
	}
	
	public void addAsofOwnerAssociationMapping(DOMWriter writer)
					throws MappingException, DocumentException {
		
		Document document = createAsofClassMapping(OwnerAssociation.class.getName(), "ASOF_OWNER");
		Element entity = document.getRootElement().element("class");	
		
		addProperty(entity, "personCode", "string", "PERSON");
		addProperty(entity, "sheetCode", "string", "SHEET");
		addProperty(entity, "sheetType", "string", "SHEET_TYPE");
		
		hibernateConfig.addDocument(writer.write(document));
		
		//System.out.println(document.asXML());
	}
	
	public void addAsofLinkAssociationMapping(DOMWriter writer)
					throws MappingException, DocumentException {
		
		Document document = createAsofClassMapping(LinkAssociation.class.getName(), "ASOF_LINK");
		Element entity = document.getRootElement().element("class");	
		
		addProperty(entity, "fromCode", "string", "FROM_CODE");
		addProperty(entity, "toCode", "string", "TO_CODE");
		addProperty(entity, "fromType", "string", "FROM_TYPE");
		addProperty(entity, "toType", "string", "TO_TYPE");
		addProperty(entity, "order", "integer", "TO_ORDER");
		addProperty(entity, "label", "string", "LINK_LABEL");
		
		hibernateConfig.addDocument(writer.write(document));
		
		//System.out.println(document.asXML());
	}
	
	private void addAsofDelegationMapping(DOMWriter writer)
					throws MappingException, DocumentException {

		Document document = createAsofClassMapping(Delegation.class.getName(), "ASOF_DELEGATION");
		Element entity = document.getRootElement().element("class");
		
		addProperty(entity, "ownerCode", "string", "OWNER");
		addProperty(entity, "personCode", "string", "PERSON");
		addProperty(entity, "sheetCode", "string", "SHEET");
		addProperty(entity, "sheetType", "string", "SHEET_TYPE");
		
		hibernateConfig.addDocument(writer.write(document));
		
		//System.out.println(document.asXML());
	}
	
	
	private void addAsofMappings() throws MappingException, DocumentException {
		DOMWriter writer = new DOMWriter();
		
		Document personMapping = createHibernatePersonSheetMapping();
		addAsofPassword(personMapping);
		addAsofStatus(personMapping);
		hibernateConfig.addDocument(writer.write(personMapping));
		
		for(Document mapping : createHibernateSheetsMappings()) {
			addAsofStatus(mapping);
			hibernateConfig.addDocument(writer.write(mapping));
		}
		
		// on ajoute les tables spécifiques à ASOF :
		addAsofOwnerAssociationMapping(writer);
		addAsofTreeAssociationMapping(writer);
		addAsofLinkAssociationMapping(writer);
		addAsofDelegationMapping(writer);
	}

}
